/* * Copyright 2014 Artur. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jaxygen.client.jaxygenclient; import com.google.gson.Gson; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.mime.FormBodyPart; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.InputStreamBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.DefaultHttpClient; import org.jaxygen.converters.json.JsonMultipartRequestConverter; import org.jaxygen.converters.sjo.SJOResponseConverter; import org.jaxygen.dto.ExceptionResponse; import org.jaxygen.dto.Response; import org.jaxygen.dto.security.SecurityProfileDTO; import org.jaxygen.security.SecurityProfile; import org.jaxygen.security.basic.SecuredMethodDescriptor; /** * Class enables Java applications for accessing Jaxygen web interface using * synchronous call. * */ public class JaxygenClient { private final String url; private final Gson gson = new Gson(); private final Session session = new Session(); private static final Logger LOGGER = Logger.getLogger(Handler.class.getName()); private class Session { public List<String> cookies = new ArrayList<String>(1); }; private class IOProxy extends InputStream implements Appendable { PipedOutputStream po = new PipedOutputStream(); PipedInputStream ps; public IOProxy() throws IOException { ps = new PipedInputStream(po); } public Appendable append(CharSequence csq) throws IOException { po.write(csq.toString().getBytes(Charset.forName("UTF-8"))); return this; } public Appendable append(CharSequence csq, int start, int end) throws IOException { po.write(csq.subSequence(start, end).toString().getBytes(Charset.forName("UTF-8"))); return this; } public Appendable append(char c) throws IOException { char[] a = {c}; po.write(new String(a).getBytes(Charset.forName("UTF-8"))); return this; } @Override public void close() throws IOException { ps.close(); super.close(); } @Override public int read() throws IOException { return ps.read(); } } private class Handler implements InvocationHandler { private final String urlBase; private final Session session; Handler(String urlBase, Session session) { this.urlBase = urlBase; this.session = session; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { final String methodUrl = urlBase + "/" + method.getName(); HttpPost post = new HttpPost(methodUrl); MultipartEntity mp = new MultipartEntity(); if (session.cookies != null) { StringBuilder cookiesStr = new StringBuilder(256); for (String cookie : session.cookies) { cookiesStr.append(cookie); cookiesStr.append(";"); } if (cookiesStr.length() > 0) { LOGGER.log(Level.INFO, "cookies: ", cookiesStr); post.setHeader("Cookie", cookiesStr.substring(0)); } } if (args != null) { for (Object o : args) { IOProxy p = new IOProxy(); String json = gson.toJson(o); //mp.addPart(o.getClass().getName(), new InputStreamBody(p, "text/json", o.getClass().getName())); mp.addPart(o.getClass().getName(), new InputStreamBody(new ByteArrayInputStream(json.getBytes(Charset.forName("UTF-8"))), "text/json", o.getClass().getName())); } } mp.addPart(new FormBodyPart("inputType", new StringBody(JsonMultipartRequestConverter.NAME))); mp.addPart(new FormBodyPart("outputType", new StringBody(SJOResponseConverter.NAME))); post.setEntity(mp); HttpResponse response = new DefaultHttpClient().execute(post); final HttpEntity e = response.getEntity(); Header[] hCookies = response.getHeaders("Set-Cookie"); if (hCookies != null) { for (Header h : hCookies) { session.cookies.add(h.getValue()); } } ObjectInputStream osi = null; final StringBuffer sb = new StringBuffer(256); try { InputStream inputProxy = new InputStream() { @Override public int read() throws IOException { int b = e.getContent().read(); if (sb.length() < 1024) { sb.append((char) b); } return b; } }; Throwable appException = null; try { osi = new ObjectInputStream(inputProxy); Response wrappedResponse = (Response) osi.readObject(); if (wrappedResponse instanceof ExceptionResponse) { ExceptionResponse exr = (ExceptionResponse) wrappedResponse; Class<Throwable> exClass = (Class<Throwable>) getClass().getClassLoader().loadClass(exr.getExceptionData().getExceptionClass()); appException = exClass.newInstance(); } if (appException == null) { if (SecurityProfile.class.equals(method.getReturnType())) { return convertDtoToSecurityProfile((SecurityProfileDTO) wrappedResponse.getDto().getResponseObject()); } else { return wrappedResponse.getDto().getResponseObject(); } } } catch (Throwable ex) { throw new InvocationTargetException(ex, "Unexpected server response: " + sb.toString()); } if (appException != null) { throw appException; } } finally { if (osi != null) { osi.close(); } } return null; } private SecurityProfile convertDtoToSecurityProfile(final SecurityProfileDTO dto) { return new SecurityProfile() { public String[] getUserGroups() { return dto.getGroups(); } public SecuredMethodDescriptor isAllowed(String className, String methodName) { String idt = className + "#" + methodName; for (String md : dto.getAllowedMethods()) { if (idt.equals(md)) { return new SecuredMethodDescriptor(className, methodName); } } return null; } public String[] getAllowedMethodDescriptors() { return dto.getAllowedMethods(); } }; } }; public JaxygenClient(final String homeURL) { this.url = homeURL; } public <T> T lookup(final String className, Class<T> remoteInterface) { Class<?> interfaces[] = {remoteInterface}; return (T) java.lang.reflect.Proxy.newProxyInstance( remoteInterface.getClassLoader(), interfaces, new Handler(url + "/" + className, session)); } }